package com.yudean.esb.cached;

import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;


public class RecvPackageCollection {
    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(RecvPackageCollection.class);
    private volatile static RecvPackageCollection singleton = null;
    private static final Map<String, Integer> counterMap = Collections.synchronizedMap(new HashMap<>());//事务当前接收的包数
    private static final Map<String, Integer> transactionTotalPackagesMap = Collections.synchronizedMap(new HashMap<>());//每个事务对应的包总数
    private static final Map<String, HashSet<String>> transactionPkg = Collections.synchronizedMap(new HashMap<>());//每个事务对应的包

    private RecvPackageCollection() {
    }

    public static RecvPackageCollection getInstance() {
        if (singleton == null) {
            synchronized (RecvPackageCollection.class) {
                if (singleton == null) {
                    singleton = new RecvPackageCollection();
                }
            }
        }
        return singleton;
    }

    /**
     * 对事务接收包进行计数
     *
     * @param transactionID
     * @param pkg
     * @param totalPkg
     */
    public synchronized static boolean addPackage(String transactionID, String pkg,
                                                  String totalPkg) {
        //检查包是否已存在
        if (isPackageExist(transactionID, pkg)) {
            return false;
        }
        int total = Integer.parseInt(totalPkg.trim());
        int nextCount;
        Integer count = counterMap.get(transactionID);
        if (count == null) {
            nextCount = 1;
            counterMap.put(transactionID, nextCount);
            transactionTotalPackagesMap.put(transactionID, new Integer(totalPkg));
            HashSet<String> pkgSet = new HashSet<String>();
            pkgSet.add(pkg);
            transactionPkg.put(transactionID, pkgSet);
        } else {
            nextCount = count + 1;
            counterMap.put(transactionID, nextCount);
            HashSet<String> pkgSet = transactionPkg.get(transactionID);
            pkgSet.add(pkg);
            transactionPkg.put(transactionID, pkgSet);
        }
        if (nextCount == total) {
            logger.debug(
                    "putPackage(): {transactionID:{} Receive package:{}, totalPackage:{}} transaction end",
                    transactionID, nextCount, totalPkg);
        }
        return true;
    }

    /**
     * 对事务接收包进行计数
     *
     * @param transactionID
     * @param pkg
     * @param totalPkg
     */
    public synchronized static boolean addPackage(String transactionID, String pkg,
                                                  String totalPkg, String forceReplace) {
        //如果包已经存在，并且不强制替换，则包重复，添加不成功
        if (isPackageExist(transactionID, pkg) && forceReplace.equals("0")) {
            return false;
        }
        int total = Integer.parseInt(totalPkg.trim());
        int nextCount;
        Integer count = counterMap.get(transactionID);
        if (count == null) {
            nextCount = 1;
            counterMap.put(transactionID, nextCount);
            transactionTotalPackagesMap.put(transactionID, new Integer(totalPkg));
            HashSet<String> pkgSet = new HashSet<String>();
            pkgSet.add(pkg);
            transactionPkg.put(transactionID, pkgSet);
        } else {
            nextCount = count + 1;
            counterMap.put(transactionID, nextCount);
            HashSet<String> pkgSet = transactionPkg.get(transactionID);
            pkgSet.add(pkg);
            transactionPkg.put(transactionID, pkgSet);
        }
        if (nextCount == total) {
            logger.debug(
                    "putPackage(): {transactionID:{} Receive package:{}, totalPackage:{}} transaction end",
                    transactionID, nextCount, totalPkg);
        }
        return true;
    }

    public synchronized static boolean isPackageExist(String transactionID, String pkg) {
        boolean isExist = false;
        HashSet<String> pkgSet = transactionPkg.get(transactionID);
        if (pkgSet != null && pkgSet.contains(pkg)) {
            isExist = true;
        }
        return isExist;
    }

    /**
     * 检查事务是否开始
     *
     * @param transactionID
     * @return
     */
    public synchronized static boolean isTransactionEnd(String transactionID) {
        boolean result = false;
        Integer totalPackages = transactionTotalPackagesMap.get(transactionID);
        Integer currentCount = counterMap.get(transactionID);
        if (totalPackages != null && currentCount != null) {
            if (totalPackages.intValue() == currentCount.intValue()) {
                result = true;
            }
        } else {
            result = false;
        }
        return result;
    }

    /**
     * 检查事务是否结束
     *
     * @param transactionID
     * @return
     */
    public static boolean isTransactionBegin(String transactionID) {
        boolean result = false;
        Integer currentCount = counterMap.get(transactionID);
        if (currentCount != null && currentCount == 1) {
            result = true;
        }
        return result;
    }
}
